package primetest.impl.dao;

import java.io.IOException;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;

import java.util.List;

import javax.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import primetest.dto.ConfigDto;
import primetest.impl.dao.ConfigDao;
import primetest.impl.dao.Transaction;

//@Stateless
public class ConfigDao implements Serializable {
	/**
	 *
	 */
	private static final long serialVersionUID = 6551770662358620809L;

	private final Logger logger = LoggerFactory.getLogger(this.getClass());

	private static List<ConfigDto> allItems = null;
	private static HashMap<String, ConfigDto> map = null;

	@Inject
	public ConfigDao() {
	}

	public List<ConfigDto> getAllList(Transaction transaction)
			throws IOException {
		if (allItems != null) {
			return allItems;
		}
		PreparedStatement prepareStatement = null;
		ResultSet resultSet = null;
		map = new HashMap<String, ConfigDto>();
		try {

			Connection connection = transaction.getResource(Connection.class);
			prepareStatement = connection.prepareStatement(GET_ALL);
			resultSet = prepareStatement.executeQuery();

			while (resultSet.next()) {
				ConfigDto configDto = makeConfigDto(transaction,
						resultSet);
				map.put(configDto.getKey(), configDto);
			}
			allItems = new ArrayList<ConfigDto>(map.values());
			return allItems;
		} catch (SQLException e) {
			throw new IOException(e);
		} finally {
			if (resultSet != null) {
				try {
					resultSet.close();
				} catch (SQLException e) {
					logger.warn(e.getMessage(), e);
				}
			}

			if (prepareStatement != null) {
				try {
					prepareStatement.close();
				} catch (SQLException e) {
					logger.warn(e.getMessage(), e);
				}
			}
		}
	}

	private ConfigDto makeConfigDto(Transaction transaction,
			ResultSet resultSet) throws SQLException, IOException {
		ConfigDto configDto = new ConfigDto(resultSet.getString(1),
				resultSet.getString(2));
		return configDto;
	}

	public void addConfig(Transaction transaction, ConfigDto configDto)
			throws IOException {
		PreparedStatement prepareStatement = null;
		ResultSet resultSet = null;
		allItems = null;

		try {
			Connection connection = transaction.getResource(Connection.class);
			prepareStatement = connection.prepareStatement(INSERT_ONE);
			prepareStatement.setString(1, configDto.getKey());
			prepareStatement.setString(2, configDto.getValue());
			prepareStatement.executeUpdate();
			map.put(configDto.getKey(), configDto);
			allItems = new ArrayList<ConfigDto>(map.values());
		} catch (SQLException e) {
			throw new IOException(e);
		} finally {
			if (resultSet != null) {
				try {
					resultSet.close();
				} catch (SQLException e) {
					logger.warn(e.getMessage(), e);
				}
			}

			if (prepareStatement != null) {
				try {
					prepareStatement.close();
				} catch (SQLException e) {
					logger.warn(e.getMessage(), e);
				}
			}
		}
	}

	public void updateConfig(Transaction transaction, ConfigDto configDto)
			throws IOException {
		PreparedStatement prepareStatement = null;
		ResultSet resultSet = null;
		allItems = null;

		try {
			Connection connection = transaction.getResource(Connection.class);
			prepareStatement = connection.prepareStatement(UPDATE_ONE);
			prepareStatement.setString(2, configDto.getKey());
			prepareStatement.setString(1, configDto.getValue());
			prepareStatement.executeUpdate();
			map.put(configDto.getKey(), configDto);
			allItems = new ArrayList<ConfigDto>(map.values());
		} catch (SQLException e) {
			throw new IOException(e);
		} finally {
			if (resultSet != null) {
				try {
					resultSet.close();
				} catch (SQLException e) {
					logger.warn(e.getMessage(), e);
				}
			}

			if (prepareStatement != null) {
				try {
					prepareStatement.close();
				} catch (SQLException e) {
					logger.warn(e.getMessage(), e);
				}
			}
		}

	}

	public ConfigDto findConfig(Transaction transaction, String key) throws IOException {
		if(allItems == null){
			logger.debug("cached no functioned in findConfig, key:" + key);
			getAllList(transaction);
		}
		ConfigDto configDto = map.get(key);
		if (configDto == null) {
			configDto = new ConfigDto(key, "");
			addConfig(transaction, configDto);
		}
		return configDto;
	}

	public void deleteConfig(Transaction transaction, String configSeq)
			throws IOException {
		PreparedStatement prepareStatement = null;
		ResultSet resultSet = null;
		allItems = null;

		try {
			Connection connection = transaction.getResource(Connection.class);
			prepareStatement = connection.prepareStatement(DELETE_ONE);
			prepareStatement.setString(1, configSeq);
			prepareStatement.executeUpdate();
			map.remove(configSeq);
			allItems = new ArrayList<ConfigDto>(map.values());
		} catch (SQLException e) {
			throw new IOException(e);
		} finally {
			if (resultSet != null) {
				try {
					resultSet.close();
				} catch (SQLException e) {
					logger.warn(e.getMessage(), e);
				}
			}

			if (prepareStatement != null) {
				try {
					prepareStatement.close();
				} catch (SQLException e) {
					logger.warn(e.getMessage(), e);
				}
			}
		}

	}


	private static final String GET_ALL = "select key_1, value_1 from s_config";
	private static final String INSERT_ONE = "insert into s_config(key_1, value_1) values (?, ?)";
	private static final String UPDATE_ONE = "update s_config set value_1 = ? where key_1 = ?";
	private static final String DELETE_ONE = "delete from s_config where key_1 = ?";
}
